package org.star.filters;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2024/1/4 11:00
 * @Description: 自定义全局过滤器
 */
@Component
public class LogGlobalFilter implements GlobalFilter, Ordered {
    Logger log = LoggerFactory.getLogger(this.getClass());

    /**
     * 设置最高优先级 保证在 获取body 之前执行
     * @return
     */
    @Override
    public int getOrder() {
        return HIGHEST_PRECEDENCE;
    }

    /**
     * http://localhost:8888/order-service-openfeign-nacos/getUserDetail?name=admin&city=杭州
     *      （1）requestPath：/order-service-openfeign-nacos/getUserDetail
     *      （2）queryParams：{name=[admin], city=[北京]}
     * @param exchange the current server exchange
     * @param chain provides a way to delegate to the next filter
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        log.info("requestPath:{}", request.getPath().value());
        if (request.getMethod().matches(HttpMethod.GET.name())) {
            log.info("queryParams:{}", request.getQueryParams());
            return chain.filter(exchange);
        } else if (request.getMethod().matches(HttpMethod.POST.name())) {
            /**
             * 获取POST方法中的body参数
             * 参考：https://blog.csdn.net/qq825478739/article/details/128407466
             */
            return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(e -> {
                byte[] bytes = new byte[e.readableByteCount()];
                e.read(bytes);
                DataBufferUtils.release(e);
                Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
                    DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
                    DataBufferUtils.retain(buffer);
                    return Mono.just(buffer);
                });

                /**
                 * repackage ServerHttpRequest
                 */
                ServerHttpRequest serverHttpRequest = new ServerHttpRequestDecorator(exchange.getRequest()) {
                    @Override
                    public Flux<DataBuffer> getBody() {
                        return cachedFlux;
                    }
                };
                /**
                 * mutate exchage with new ServerHttpRequest
                 */
                ServerWebExchange mutatedExchange = exchange.mutate().request(serverHttpRequest).build();
                /**
                 * read body string with default messageReaders
                 */
                return ServerRequest.create(mutatedExchange, HandlerStrategies.withDefaults().messageReaders()).bodyToMono(String.class)
                        .doOnNext(objectValue -> {
                        }).then(chain.filter(mutatedExchange));
            });
        }
        return chain.filter(exchange);
    }

}
